package com.tansun.easycare.rule.datamodel.web;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.tansun.easycare.rule.datamodel.entity.RuleDataparams;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageInfo;
import com.tansun.easycare.core.utils.ResponseTable;
import com.tansun.easycare.rule.common.Constant;
import com.tansun.easycare.rule.common.DataCache;
import com.tansun.easycare.rule.common.ReferenceModel;
import com.tansun.easycare.rule.common.ResMessage;
import com.tansun.easycare.rule.common.RuleBaseController;
import com.tansun.easycare.rule.common.SelBean;
import com.tansun.easycare.rule.common.model.ResponseVO;
import com.tansun.easycare.rule.common.model.RuleSetParamInfo;
import com.tansun.easycare.rule.common.service.RuleSetParmOperator;
import com.tansun.easycare.rule.datacomponent.service.IDataComponentService;
import com.tansun.easycare.rule.datamodel.dao.RuleDatamodelDao;
import com.tansun.easycare.rule.datamodel.entity.RuleDatamodel;
import com.tansun.easycare.rule.datamodel.entity.RuleDataset;
import com.tansun.easycare.rule.datamodel.model.DataSourceVo;
import com.tansun.easycare.rule.datamodel.service.DataModelService;
import com.tansun.easycare.rule.referencedata.dao.RuleReferenceDataDao;
import com.tansun.easycare.rule.referencedata.entity.RuleReferenceData;
import com.tansun.easycare.rule.utils.JsonUtil;
import com.tansun.rule.common.RuleModelTypeEnum;
import com.tansun.rule.utils.StringUtils;

/**
 * 数据模型Action
 *
 * @author Lph
 */
@RestController
@RequestMapping(value = "/ruleProj/dataModel")
public class DataModelController extends RuleBaseController {
    private static final Logger logger = LoggerFactory.getLogger(DataModelController.class);

    @Autowired
    private DataModelService dataModelService;

    @Autowired
    private RuleReferenceDataDao ruleReferenceDataDao;


    @Autowired
    private IDataComponentService dataComponentService;
    
    @Autowired
    private RuleDatamodelDao RuleDatamodelDao;
    




    /**
     * 进入数据模型首页 ljt vue
     */
    @RequestMapping("index")
    public ResponseTable<RuleDatamodel> index(@RequestBody RuleDatamodel ruleDatamodel) throws Exception {
        PageInfo<RuleDatamodel> pageInfo = this.dataModelService.findRuleDatamodelPage(ruleDatamodel.getPage(),ruleDatamodel);
        ResponseTable<RuleDatamodel>  resVo  = new  ResponseTable<RuleDatamodel>(pageInfo);
        return resVo;
    }
    /**
     * 数据模型点击进入数据集页面 vue
     * @return
     * @throws Exception
     */
    @RequestMapping("datasetlist")
    public ResponseTable<RuleDataset> index(@RequestBody RuleDataset ruleDataset) throws Exception {
        PageInfo<RuleDataset> pageInfo = this.dataModelService.findRuleDatasetPage(ruleDataset.getPage(),
                ruleDataset);
        ResponseTable<RuleDataset>  resVo  = new  ResponseTable<RuleDataset>(pageInfo);
        return resVo;
        //
    }
    /**
     * 保存或修改数据模型
     *
     * @param ruleDatamodel          数据模型信息
     * @return 操作是否成功的json串
     */
    @RequestMapping(value="saveOrUpdate")
    public ResponseVO saveOrUpdate(@RequestBody RuleDatamodel ruleDatamodel)
            throws Exception {
        ResponseVO ret = new ResponseVO();
        try {
            if(!StringUtils.isEmpty(ruleDatamodel.getId())) {
                ruleDatamodel.setUpdateDate(new Date());
                this.dataModelService.updateDatamodel(ruleDatamodel);
            }else {
                //添加名称校验
            	RuleDatamodel rdm = new RuleDatamodel();
                rdm.setProjectCode(ruleDatamodel.getProjectCode());
                List<RuleDatamodel> list = this.dataModelService.queryRuleDatamodelList(rdm);
                for (RuleDatamodel datamodel : list) {
                    if (datamodel.getId().equals(ruleDatamodel.getId())) {
                        continue;
                    } else {

                        if (datamodel.getName().equals(ruleDatamodel.getName())) {
                            ret.setDescription("数据集名称重复,请修改！");;
                            ret.setStatus(ResponseVO.ERROR);
                            return ret;
                        } else if (datamodel.getChzn().equals(ruleDatamodel.getChzn())) {
                            ret.setDescription("数据集中文名称重复,请修改！");;
                            ret.setStatus(ResponseVO.ERROR);
                            return ret;
                        }
                    }
                }
                ruleDatamodel.setCreateDate(new Date());
                ruleDatamodel.setUpdateDate(new Date());
                ruleDatamodel.setId(StringUtils.getUUID().replace("-", ""));
                this.dataModelService.saveDatamodel(ruleDatamodel);
            }
            DataCache.paramChange(ruleDatamodel.getProjectCode());
        } catch (Exception e) {
            logger.debug(ExceptionUtils.getStackTrace(e));
            ret.setDescription(e.getMessage());;
            ret.setStatus(ResponseVO.ERROR);
            return ret;
        }
        return ret;
    }
    /**
     * 保存或修改数据集
     *
     * @param dm          数据集信息
     * @return 操作是否成功的json串
     */
    @RequestMapping(value="saveOrUpdateDadaset",produces = "application/json; charset=utf-8")
    @ResponseBody
    public ResponseVO saveOrUpdateDadaset(@RequestBody RuleDataset dm)
            throws Exception {
        ResponseVO ret = new ResponseVO();
        try {
            if(!StringUtils.isEmpty(dm.getId())){    
       
                this.dataModelService.saveAndUpdateRef(dm);
            }else{
                dm.setIsbuiltin("0");//非内置变量
                // dm.setCode(modelName);
                //添加名称校验
                RuleDataset ruleDataset = new RuleDataset();
                ruleDataset.setProjectcode(dm.getProjectcode());
                ruleDataset.setRankRelationId(dm.getRankRelationId());
                List<RuleDataset> list = this.dataModelService.queryRuleDataList(ruleDataset);
                for (RuleDataset dataset : list) {
                    if (dataset.getName().equals(dm.getName())) {
                        ret.setDescription("数据集名称重复,请修改！");;
                        ret.setStatus(ResponseVO.ERROR);
                        return ret;
                    } else if (dataset.getChzn().equals(dm.getChzn())) {
                        ret.setDescription("修数据集中文名称重复,请改！");;
                        ret.setStatus(ResponseVO.ERROR);
                        return ret;
                    }
                }
                
                dm.setParamType("ALL");
                
                this.dataModelService.save(dm);
            }
            DataCache.paramChange(dm.getProjectcode());
        } catch (Exception e) {
        	e.printStackTrace();
            logger.debug(ExceptionUtils.getStackTrace(e));
            ret.setDescription("新增或者修改数据集失败");;
            ret.setStatus(ResponseVO.ERROR);
            return ret;
        }
        ret.setDescription("保存成功");
        return ret;
    }

    /**
     * 删除数据模型
     * @param ids
     * @return 是否删除成功json串
     */
    @RequestMapping(value="delectDatamodel",produces = "application/json; charset=utf-8")
    public ResponseVO delectDatamodel(@RequestBody String[] ids) {
        ResponseVO ret = new ResponseVO();
        if (ids == null) {
            ret.setDescription("删除失败，参数有误");;
            ret.setStatus(ResponseVO.ERROR);
            return ret;
        }
        boolean success = false;
        try {
            for (String id : ids) {
                this.dataModelService.deleteDataModelPlusById(id);
            }
            success = true;
        } catch (Exception e) {
            logger.debug(ExceptionUtils.getStackTrace(e));
            ret.setDescription("删除失败,原因："+e.getMessage());;
            ret.setStatus(ResponseVO.ERROR);
            return ret;
        }
        if (!success) {
            ret.setDescription("删除失败，没有找到对应数据");
            ret.setStatus(ResponseVO.ERROR);
            return ret;
        }
        ret.setDescription("删除成功！");
        return ret;
    }
    /**
     * 删除数据集
     *
     * @param ids 数据集的id集合
     * @return 是否删除成功json串
     */
    @RequestMapping(value="delectDataset",produces = "application/json; charset=utf-8")
    public ResponseVO delectDataset(@RequestBody String[] ids) {
        ResponseVO ret = new ResponseVO();
        if (ids == null) {
            ret.setDescription("删除失败，参数有误");;
            ret.setStatus(ResponseVO.ERROR);
            return  ret;
        }
        boolean success = false;
        try {
            for (String id : ids) {
                this.dataModelService.deleteDataModelById(id);
            }
            success = true;
        } catch (Exception e) {
            logger.debug(ExceptionUtils.getStackTrace(e));
            ret.setDescription("删除失败,原因："+e.getMessage());;
            ret.setStatus(ResponseVO.ERROR);
            return  ret;
        }
        if (!success) {
            ret.setDescription("删除失败，没有找到对应数据");;
            ret.setStatus(ResponseVO.ERROR);
            return  ret;
        }
        ret.setDescription( "删除成功");
        return ret;
    }

    /**
     * 查询引用变量的模块
     * @param map
     * @return
     * @throws Exception
     */
    @RequestMapping("reference")
    public ResponseTable<ReferenceModel> reference(@RequestBody Map<String,Object> map) throws Exception {
            PageInfo<ReferenceModel> pageInfo = this.dataModelService.findReferenceData(map);
            ResponseTable<ReferenceModel>  resVo  = new  ResponseTable<>(pageInfo);
            return resVo;
    }
    /**
     * 数据查询时获取数据模型列表
     *
     * @param projectCode 规则项目编码
     * @param modelName   数据模型编码（固定取dataModel）
     * @return 数据模型json串
     */

    @RequestMapping("getJsonArray")
    @ResponseBody
    public ResponseTable<RuleDataset> getJsonArray(@RequestBody RuleDataset ruleDataset) throws Exception {
       PageInfo<RuleDataset> pageInfo = dataModelService.findDatasetForMove(ruleDataset);
        ResponseTable<RuleDataset> responseTable = new ResponseTable<>(pageInfo);
        return responseTable;
    }

    /** =======================================以上为vue版本所用到的方法============================*/
    /**
     * 查询管理页面
     */
    @RequestMapping("list")
    public String list(HttpServletRequest request, HttpServletResponse response, String projectCode,
                       RuleDataset ruleDataset, ModelMap map) throws Exception {
    	if (StringUtils.isEmpty(projectCode)) {
            projectCode = this.getCurrProjectCode();
        }
        ruleDataset.setProjectcode(projectCode);

        PageInfo<RuleDataset> page = this.dataModelService.findListPageByInfo(new Page<RuleDataset>(),
                ruleDataset);
        map.put("page", page);
        map.put("projectCode", projectCode);
        map.put("vo", JsonUtil.object2json(page.getList()));//page.getList():获取符合查询条件的ruleDataset object数据
        return "rule/datamodel/index";
    }
    /**
     * 查询管理页面
     */
    @RequestMapping("datamodelList")
    public String datamodelList(HttpServletRequest request, HttpServletResponse response, String projectCode,
                       RuleDatamodel ruleDatamodel, ModelMap map) throws Exception {
    	if (StringUtils.isEmpty(projectCode)) {
            projectCode = this.getCurrProjectCode();
        }
        ruleDatamodel.setProjectCode(projectCode);

        PageInfo<RuleDatamodel> page = this.dataModelService.findDatamodelListPageByInfo(new Page<RuleDatamodel>(),
                ruleDatamodel);
        map.put("page", page);
        map.put("projectCode", projectCode);
        map.put("vo", JsonUtil.object2json(page.getList()));//page.getList():获取符合查询条件的ruleDataset object数据
        return "rule/datamodel/dataModelIndex";
    }
//    /**
//     * 进入数据模型管理页面（原方法在上面）
//     * ZL改造，套一层数据模型
//     */
//    @RequestMapping("index")
//    public String index(HttpServletRequest request, HttpServletResponse response, String projectCode,
//                        RuleDatamodel ruleDatamodel, ModelMap map) throws Exception {
//        if (StringUtils.isEmpty(projectCode)) {
//            projectCode = this.getCurrProjectCode();
//        }
//        ruleDatamodel.setProjectcode(projectCode);
//        Page<RuleDatamodel> page = this.dataModelService.findRuleDatamodelPage(new Page<RuleDatamodel>(request, response),
//        		ruleDatamodel);
//        map.put("page", page);
//        map.put("projectCode", projectCode);
//        map.put("rankRelationId",ruleDatamodel.getRankRelationId());
//        return "rule/datamodel/dataModelIndex";
//    }
    /**
     * @return status状态值 和所选中的该条数据的具体传人的各项数据，一般用于修改功能对应datamodel主页面、在//设置是否选中数据(checkbox)的，seleDetail()中被引用
     */  
    @RequestMapping("getRuleDataset")
    @ResponseBody
    public ResponseVO getRuleDataset(String id) {
        ResponseVO responseVO = new ResponseVO();
        responseVO.setStatus(200);
        RuleDataset ruleDataset = this.dataModelService.get(id);
        responseVO.setData(ruleDataset);
        return responseVO;

    }
    /**
     * @return status状态值 和所选中的该条数据的具体传人的各项数据，一般用于修改功能对应datamodel主页面、在//设置是否选中数据(checkbox)的，seleDetail()中被引用
     */  
    @RequestMapping("getRuleDatamodel")
    @ResponseBody
    public ResponseVO getRuleDatamodel(String id) {
        ResponseVO responseVO = new ResponseVO();
        responseVO.setStatus(200);
        RuleDatamodel ruleDatamodel = RuleDatamodelDao.getById(id);
        responseVO.setData(ruleDatamodel);
        return responseVO;

    }
    /**
     * 数据模型类型
     *
     * @return 数据模型类型json串
     */
    @RequestMapping("getParamType")
    @ResponseBody
    public String getParamType(HttpServletRequest request, HttpServletResponse response) throws Exception {
        List<SelBean> list = new ArrayList<SelBean>();
        list.add(new SelBean("输入", Constant.DATAMODEL_PARAMTYPE_IN));
        list.add(new SelBean("输出", Constant.DATAMODEL_PARAMTYPE_OUT));
        list.add(new SelBean("输入和输出", Constant.DATAMODEL_PARAMTYPE_ALL));
        list.add(new SelBean("仅复用", Constant.DATAMODEL_PARAMTYPE_OTH));
        return JSONArray.toJSONString(list);
    }
    /*
     * 保存或修改数据模型
     *
     * @param dm          数据模型信息
     * @param projectCode 规则项目编码
     * @param modelName   数据模型编码（固定取dataModel）
     * @return 操作是否成功的json串
     */
    @RequestMapping(value="firstDefinition",produces = "application/json; charset=utf-8")
    @ResponseBody
    public String firstDefinition(@ModelAttribute RuleDatamodel dm, HttpServletRequest request, String projectCode, String modelName)
            throws Exception {
        ResMessage msg = null;
        try {
            projectCode = super.getCurrProjectCode();
            dm.setProjectCode(projectCode);
            dm.setId(StringUtils.getUUID().replace("-", ""));
            dm.setCreateDate(new Date());
            this.dataModelService.firstDefinition(dm);
        } catch (Exception e) {
            logger.debug(ExceptionUtils.getStackTrace(e));
            msg = new ResMessage("failure", "保存文件失败");
            return JSONArray.toJSONString(msg);
        }
        msg = new ResMessage("success", "初始化成功");
        return JSONArray.toJSONString(msg);
    }
    /**
     * 验证数据模型名是否已经存在
     *
     * @param projectCode 规则项目编码
     * @param modelName   数据模型编码（固定取dataModel）
     * @param key         数据模型英文名
     * @param initValue   空值
     * @return 操作是否成功的json串
     */
    @RequestMapping(value="nameUniqueCheck",produces = "application/json; charset=utf-8")
    @ResponseBody
    public String nameUniqueCheck(HttpServletRequest request, String key, String initValue) throws Exception {
        Map<String, Object> result = new HashMap<String, Object>();
        if (key == null || "".equals(key)) {
            result.put("result", "参数有误，服务器未接收到关键字");
            return JSONArray.toJSONString(result);
        }
        String projectCode = getCurrProjectCode();
        RuleDataset ruleDataset = new RuleDataset();
        ruleDataset.setProjectcode(projectCode);
        ruleDataset.setName(key);
        List<RuleDataset> list = this.dataModelService.queryRuleDataList(ruleDataset);
        if (list != null && list.size() > 0) {
            if (list.get(0).getName().equals(initValue)) {
                result.put("result", "名称重复，请使用其他有效名称");
                return JSONArray.toJSONString(result);
            }
        }

        result.put("result", true);
        return JSONArray.toJSONString(result);
    }


    //查询变量引用的模块信息
    @RequestMapping(value="referenceData",produces = "application/json; charset=utf-8")
    @ResponseBody
    public String reference2(String className,String projectCode, String paramName, ModelMap map) throws Exception {
        RuleReferenceData referenceData = new RuleReferenceData();
        if (StringUtils.isEmpty(projectCode)) {
            projectCode = this.getCurrProjectCode();
        }
        referenceData.setProjectCode(projectCode);
        referenceData.setClassName(className);
        referenceData.setNameen(paramName);
        List<RuleReferenceData> list = this.ruleReferenceDataDao.findPublishRuleReferenceList(referenceData);
        List<ReferenceModel> refList = new ArrayList();
        ReferenceModel referenceModel = null;
        Map<String, ReferenceModel> hmap = new HashMap();
        for (RuleReferenceData ruleReferenceData : list) {
            referenceModel = new ReferenceModel();
            referenceModel.setFlowName(ruleReferenceData.getRefName());
            referenceModel.setReferenceName(RuleModelTypeEnum.getName(ruleReferenceData.getModelType()));
            referenceModel.setReferenceVer(ruleReferenceData.getVersion());
            hmap.put(ruleReferenceData.getManageId() + ruleReferenceData.getVersion(), referenceModel);
            // refList.add(referenceModel);
        }
        refList.addAll(hmap.values());
        return JSONArray.toJSONString(refList);
    }
    
//获取数据源(导入弹出框第一个选项触发的方法)
    @RequestMapping("dataSource")
    public String dataSource(Integer index, @RequestParam(defaultValue = "") String nameCn, ModelMap map) throws Exception {
        List<?> dataList;
        Map<?,?> parseObject = JSON.parseObject(dataComponentService.getDataFromGate(), Map.class);
        dataList = (List<?>) parseObject.get("dataSourceList");
        map.addAttribute("data", dataList);
        map.addAttribute("ind", index);
        map.addAttribute("nameCn1", URLDecoder.decode(nameCn, "UTF-8"));
        return "rule/datamodel/dataSource";
    }
 
    @RequestMapping("savedb")
    @ResponseBody
    public ResMessage savedb(DataSourceVo vo) throws Exception {
        ResMessage msg = null;
        try {
            dataModelService.ToEntity(vo, this.getCurrProjectCode());
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            msg = new ResMessage("failure", e.getMessage());
            return msg;
        }
        msg = new ResMessage("success", "保存成功");
        return msg;
    }
    
    /**
     * 数据模型模板下载
     */
    @RequestMapping(value ="/downModelFile",method=RequestMethod.POST)
    private void downModelFile(HttpServletResponse response) throws IOException {
    	InputStream in = this.getClass().getResourceAsStream("/ImportTemplate/import_template.xls");
    	OutputStream os = response.getOutputStream();
        try {
            response.setHeader("Content-Disposition", "attachment; filename=import_template.xls");
            response.setContentType("application/octet-stream; charset=utf-8");
			int temp = 0;
			while ((temp = in.read()) != -1) { os.write(temp); }
            os.flush();
        } finally {
        	if (in != null) {
        		in.close();
            }
            if (os != null) {
                os.close();
            }
        }
    }
    //--以上是vue数据模型模板导出方法
    //修改变量时候，查看变量是否被引用
    @RequestMapping(value="referenceDataParam",produces = "application/json; charset=utf-8")
    @ResponseBody
    public ResponseVO reference3(@RequestBody RuleDataparams ruleDataparams) throws Exception {
        String projectCode = ruleDataparams.getProjectcode();
        String className = ruleDataparams.getClassName();
        String paramName = ruleDataparams.getName();
        ResponseVO responseVO = new ResponseVO();
        responseVO.setStatus(ResponseVO.OK);
        RuleReferenceData referenceData = new RuleReferenceData();
        if (StringUtils.isEmpty(projectCode)) {
            projectCode = this.getCurrProjectCode();
        }
        referenceData.setProjectCode(projectCode);
        referenceData.setClassName(className);
        referenceData.setNameen(paramName);
        List<RuleReferenceData> list = new ArrayList<>();
        try {
            list = this.ruleReferenceDataDao.findPublishRuleReferenceList(referenceData);
        }catch (Exception e){
            responseVO.setStatus(ResponseVO.ERROR);
            responseVO.setData(false);
            return responseVO;
        }
        if(list!=null&&list.size()>0){
            responseVO.setData(true);
        }
        return responseVO;
    }
}
